#-*- coding: utf-8 -*-

import logging


from google.appengine.api import memcache
from waveapi import robot
from waveapi import appengine_robot_runner
from waveapi import element
from django.http import HttpResponse
from DBController import *
from djapp import diff
import passwords

REMOVE = 0
ADD = 1
ACTION = ['REMOVE', 'ADD']

INLINE_BLIP_TYPE = element.Element.INLINE_BLIP_TYPE
LINE_TYPE = element.Line.class_type
NEW_LINE_TYPE = 'simple_line'
BULLET_LINE_TYPE = 'bullet_line'


def lower(request):
    c = DBController()
    c.lower()
    return HttpResponse("success.")     

def apply_changes(blip, change_list):
    logging.warning("changelist: %s" % change_list)
    for change in change_list:
        if change['action'] == ADD:
            i = 1
            while i < len(change['text']) and change['text'][i] == ' ':
                i += 1
            i += change['range'][0]
            if change['range'][0] == len(blip.text):
                blip.append(change['text'], change['annotation'] or None)
            elif change['range'][0] != 0:
                blip.at(change['range'][0]).insert(change['text'], change['annotation'] or None)
            else:
                blip.at(change['range'][0]).insert(change['text'])
                blip_ref = blip.range(1, change['range'][1])
                for ann in change['annotation']:
                    blip_ref.annotate(*ann)
            blip.range(*change['range']).clear_annotation("link/wave")
            for ann in change['annotation']:
                if ann[0] == "link/wave":
                    blip.range(i, change['range'][1]).annotate(*ann)
                    break
        if change['action'] == REMOVE:
            if change['range'][0] == 0:
                change['range'] = (change['range'][0], change['range'][1] + 1)
            blip.range(*change['range']).delete()

def value_type(value):
    if type(value) == unicode:
        return unicode
    if value.type == LINE_TYPE:
        if value.serialize()['properties'] == {}:
            return NEW_LINE_TYPE
        return BULLET_LINE_TYPE
    return value.type

def redraw_blip(wave, blip, text, annotation, dot_positions, blip_pos, header):
    for el_idx in blip._elements:
        if blip._elements[el_idx].type == INLINE_BLIP_TYPE:
            wave.delete(blip._elements[el_idx].id)
    blip.all().replace(text)
    wave.title = header
    for pos in dot_positions:
        blip.at(pos).replace(element.Line(line_type = element.Line.TYPE_LI))
    for ann in annotation:
        blip.range(ann['range']['start'], ann['range']['end']).annotate(ann['name'], ann['value'])
    i = 0
    for pos in blip_pos:
        blip.insert_inline_blip(pos + i)
        i += 1


def get_root_blip_formating(header, wave_dict):
    rslt = u"\n" + header + "\n"
    blip_text = u'\n' + header + '\n'
    annotation = []
    blip_pos = []
    dot_pos = []
    annotation.append({'name': 'style/fontWeight', 'value': 'bold', 'range': {'start': 1, 'end': len(header) + 1}})
    annotation.append({'name': 'style/fontSize', 'value': '18pt', 'range': {'start': 1, 'end': len(header) + 1}})
    
    for sec_idx in wave_dict:
        if len(wave_dict[sec_idx]) > 0:
            begin = len(rslt)
            dot_pos.append(begin)            
            rslt += '\n' + wave_dict[sec_idx].title
            blip_text += '\n' + wave_dict[sec_idx].title + ' '
            blip_pos.append(len(rslt))
            annotation.append({'name': 'style/fontWeight', 'value': 'bold', 'range': {'start': begin, 'end': len(rslt)}})
            annotation.append({'name': 'style/fontSize', 'value': '14pt', 'range': {'start': begin, 'end': len(rslt)}})
    rslt += '\n'
    return rslt, blip_text, annotation, dot_pos, blip_pos

def printwavelist(db_updated = True):
    has_changes = memcache.get("has_changes")
    if has_changes == False: #not none or true
        return HttpResponse("There are no changes. Catalogs have not been updated.")
    myRobot = robot.Robot(passwords.ROBOT_NAME,
        image_url = passwords.IMAGE_URL,
        profile_url = passwords.PROFILE_URL)
    myRobot.setup_oauth(passwords.CONSUMER_KEY, passwords.CONSUMER_SECRET, \
            server_rpc_base='http://www-opensocial.googleusercontent.com/api/rpc')
    appengine_robot_runner.run(myRobot)
    db_controller = memcache.get("db_controller")
    if not db_controller or db_updated:
        db_controller = DBController()
        memcache.add("db_controller", db_controller, 600)
        
    wave_list = db_controller.get_all()
    success = True
    for i in db_controller.subtags:
        try:
            edited_wave = myRobot.fetch_wavelet(db_controller.subtags[i]['wave_id'])
            cur_sections = wave_list[i]
            text, blip_text, annotation, dot_pos, blip_pos = get_root_blip_formating(db_controller.subtags[i]['header'], cur_sections)
            root_blip = edited_wave.root_blip
            if blip_text.strip() != root_blip.text.strip():
                redraw_blip(edited_wave, root_blip, text, annotation, dot_pos, blip_pos, db_controller.subtags[i]['header'])
                myRobot.submit(edited_wave)
                edited_wave = myRobot.fetch_wavelet(db_controller.subtags[i]['wave_id'])
                root_blip = edited_wave.root_blip
            sector_keys = filter(lambda x: len(cur_sections[x]) > 0, cur_sections) #choose only non-empty elements
            sector_keys.sort()
            sec_id = 0
            offsets = root_blip._elements.keys()
            offsets.sort()
            for offset in offsets:
                el = root_blip._elements[offset]
                if el.type == INLINE_BLIP_TYPE:
                    blip = edited_wave.blips.get(el.id)
                    key = sector_keys[sec_id]
                    #if len(cur_sections[key]) > 0:
                    new_text = unicode(cur_sections[key])
                    old_text = blip.text #WHAT BLIP!?!?
                    if new_text.strip() != old_text.strip():
                        logging.warning("WTF")
                        dif = diff.Diff(old_text[1:], new_text, 
                              blip.annotations.serialize(), cur_sections[key].annotation)
                        change_list = dif.get_diff_list()
                        apply_changes(blip, change_list)
                    sec_id+=1
            myRobot.submit(edited_wave)
        except:
            logging.error("Failed to get wave", exc_info=True)
            success = False
            continue
    if success:
        if not memcache.set("has_changes", False):
            memcache.add("has_changes", False)
        return HttpResponse('<h1>Success.</h1>')
    else:
        return HttpResponse('<h1>Update failed.</h1>')

def print_wave_list(request):
    return printwavelist()

def updatewavelist():
    pass
